package math.region;

import math.vec2;

public class AABB2 implements Surface2
{
    
    public static AABB2 interp(
            AABB2 aA, 
            AABB2 aB, 
            double aInterpTerm)
    {
        vec2 interpMin = vec2.lerp(aA.mMin, aB.mMin, aInterpTerm);
        vec2 interpMax = vec2.lerp(aA.mMax, aB.mMax, aInterpTerm);
        return new AABB2(interpMin, interpMax);
    }
    
    
    /** Euclidean minimum location */
    public vec2 mMin;
    
    /** Euclidean maximum location */
    public vec2 mMax;
    
    
    public AABB2()
    {
        this.mMin = new vec2();
        this.mMax = new vec2();
    }
    
    public AABB2(
            vec2 aMin, 
            vec2 aMax)
    {
        this.set(aMin, aMax);
    }
    
    
    public final void set(
            vec2 aMin, 
            vec2 aMax)
    {
        this.mMin.set(aMin);
        this.mMax.set(aMax);
    }
    
    public final void set(AABB2 aOther)
    {
        this.set(aOther.mMin, aOther.mMax);
    }
    
    public void extendToContain(vec2 aPoint)
    {
        if (aPoint.x < this.mMin.x)
        {
            this.mMin.x = aPoint.x;
        }
        else if (aPoint.x > this.mMax.x)
        {
            this.mMax.x = aPoint.x;
        }
        if (aPoint.y < this.mMin.y)
        {
            this.mMin.y = aPoint.y;
        }
        else if (aPoint.y > this.mMax.y)
        {
            this.mMax.y = aPoint.y;
        }
    }
    
    public void extendToContain(AABB2 box)
    {
        this.extendToContain(box.mMin);
        this.extendToContain(box.mMax);
    }
    
    public void transl(vec2 aTransl)
    {
        this.mMin.add(aTransl);
        this.mMax.add(aTransl);
    }
    
    
    public boolean overlaps(AABB2 aOther)
    {
        return (
            (this.mMin.x < aOther.mMax.x && this.mMax.x > aOther.mMin.x) &&
            (this.mMin.y < aOther.mMax.y && this.mMax.y > aOther.mMin.y)
        );
    }
    
    public boolean contains(vec2 aPoint)
    {
        return (
            (aPoint.x >= this.mMin.x && aPoint.x < this.mMax.x) &&
            (aPoint.y >= this.mMin.y && aPoint.y < this.mMax.y)
        );
    }
    
    
    public vec2 size()
    {
        return new vec2(
            this.mMax.x - this.mMin.x, 
            this.mMax.y - this.mMin.y
        );
    }
    
    
    public vec2[] extrema()
    {
        vec2[] extrema = new vec2[4];
        extrema[0] = new vec2(this.mMin.x, this.mMin.y);
        extrema[1] = new vec2(this.mMin.x, this.mMax.y);
        extrema[2] = new vec2(this.mMax.x, this.mMin.y);
        extrema[3] = new vec2(this.mMax.x, this.mMax.y);
        return extrema;
    }
    
    
    public AABB2 copy()
    {
        AABB2 copy = new AABB2();
        copy.set(this);
        return copy;
    }
    
    
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("AABB2\n   Min: ");
        sb.append(this.mMin);
        sb.append("\n   Max: ");
        sb.append(this.mMax);
        return sb.toString();
    }
    
}
